#include "ModelClass.h"
#include "XgeModelApi.h"

#include <wchar.h>
#include <locale.h>

#include <emscripten/bind.h>
using namespace emscripten;

std::string ws2s1(const std::wstring& ws)
{  
	std::string curLocale = setlocale(LC_ALL, NULL); // curLocale = "C";  

	setlocale(LC_ALL, "chs");  

	const wchar_t* _Source = ws.c_str();  
	size_t _Dsize = 2 * ws.size() + 1;  
	char *_Dest = new char[_Dsize];  
	memset(_Dest,0,_Dsize);  
	wcstombs(_Dest,_Source,_Dsize);  
	std::string result = _Dest;  
	delete []_Dest;  

	setlocale(LC_ALL, curLocale.c_str());  

	return result;  
}  

std::wstring s2ws1(const std::string& s)  
{  
	setlocale(LC_ALL, "chs");  

	const char* _Source = s.c_str();  
	size_t _Dsize = s.size() + 1;  
	wchar_t *_Dest = new wchar_t[_Dsize];  
	wmemset(_Dest, 0, _Dsize);  
	mbstowcs(_Dest,_Source,_Dsize);  
	std::wstring result = _Dest;  
	delete []_Dest;  

	setlocale(LC_ALL, "C");  

	return result;  
} 

namespace NGIS
{
	namespace Model
	{
		extern "C" NGISMODEL_API const char* NGISMODEL_CALLCONV getVersion()
		{
			return "1.0.0.1";
		}

		extern "C" NGISMODEL_API IModelClass* NGISMODEL_CALLCONV createModelClass()
		{
			return new CModelClass();
		}

		//////////////////////////////////////////////////////////////////////////
		//
		//
		//
		//////////////////////////////////////////////////////////////////////////
		float getVersion_js()
		{
			return 2.0;
		};

		int createModelClass_js()
		{
			CModelClass* modelClass = new CModelClass();
			return (int)modelClass;
		}

		void setModelName(int modelObj, std::wstring name)
		{
			CModelClass* modelClass = (CModelClass*)modelObj;
			std::string nameStr = ws2s1(name);
			modelClass->setName(nameStr);
		}

		std::wstring getModelName(int modelObj)
		{
			CModelClass* modelClass = (CModelClass*)modelObj;
			std::string nameStr = modelClass->getName();
			return s2ws1(nameStr);
		}

		void setModelUID(int modelObj, std::string uid)
		{
			CModelClass* modelClass = (CModelClass*)modelObj;
			modelClass->setUID(uid);
		}

		std::string getModelUID(int modelObj)
		{
			CModelClass* modelClass = (CModelClass*)modelObj;
			return modelClass->getUID();
		}

		void setModelExecutionStyle(int modelObj, EExecutionStyle pStyle)
		{
			CModelClass* modelClass = (CModelClass*)modelObj;
			modelClass->setExecutionStyle(pStyle);
		}

		EExecutionStyle getModelExecutionStyle(int modelObj)
		{
			CModelClass* modelClass = (CModelClass*)modelObj;
			return modelClass->getExecutionStyle();
		}

		int getModelAttribute(int modelObj)
		{
			CModelClass* modelClass = (CModelClass*)modelObj;
			IModelAttribute* modelAttribute = modelClass->getModelAttribute();
			return (int)modelAttribute;
		}

		int getModelBehavior(int modelObj)
		{
			CModelClass* modelClass = (CModelClass*)modelObj;
			IModelBehavior* modelBehavior = modelClass->getModelBehavior();
			return (int)modelBehavior;
		}

		int getModelRuntime(int modelObj)
		{
			CModelClass* modelClass = (CModelClass*)modelObj;
			IModelRuntime* modelRuntime = modelClass->getModelRuntime();
			return (int)modelRuntime;
		}

		bool loadFromXmlStream(int modelObj, std::wstring xmlStr)
		{
			CModelClass* modelClass = (CModelClass*)modelObj;
			std::string xml_str = ws2s1(xmlStr);
			return modelClass->LoadFromXmlStream(xml_str.c_str());
		}

		std::wstring formatToXmlStream(int modelObj)
		{
			CModelClass* modelClass = (CModelClass*)modelObj;
			std::string xml_str="";
			modelClass->FormatToXmlStream(xml_str);
			return s2ws1(xml_str);
		}

		bool releaseModelClass(int modelObj)
		{
			CModelClass* modelClass = (CModelClass*)modelObj;
			if (modelClass)
			{
				modelClass->release();
				return true;
			}
			return false;
		}

		bool compareModelClass_object(int modelObj1, int modelObj2, bool withRuntime)
		{
			CModelClass* modelClass1 = (CModelClass*)modelObj1;
			CModelClass* modelClass2 = (CModelClass*)modelObj2;
			if (modelClass1 && modelClass2)
			{
				std::string obj, name;
				return modelClass1->compareOther(modelClass2, withRuntime, obj, name);
			}

			return false;
		}

		bool compareModelClass_xml(std::wstring xmlStr1, std::wstring xmlStr2, bool withRuntime)
		{
			CModelClass* modelClass1 = new CModelClass();
			CModelClass* modelClass2 = new CModelClass();
			std::string xml_str1 = ws2s1(xmlStr1);
			modelClass1->LoadFromXmlStream(xml_str1.c_str());
			std::string xml_str2 = ws2s1(xmlStr2);
			modelClass2->LoadFromXmlStream(xml_str2.c_str());
			if (modelClass1 && modelClass2)
			{
				std::string obj, name;
				bool retVal = modelClass1->compareOther(modelClass2, withRuntime, obj, name);
				modelClass1->release();
				modelClass2->release();
				return retVal;
			}
			return true;
		}

		//////////////////////////////////////////////////////////////////////////
		//
		//
		//
		//////////////////////////////////////////////////////////////////////////
		int getLocalAttributeCount(int modelAttributeObj)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			return modelAttribute->getLocalAttributeCount();
		}

		ELocalizationType getLocalAttributeByIndex_LocalType(int modelAttributeObj, int idx)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			LocalAttribute pLocalAttribute;
			modelAttribute->getLocalAttribute(idx, pLocalAttribute);
			return pLocalAttribute.localType;
		}

		std::wstring getLocalAttributeByIndex_LocalName(int modelAttributeObj, int idx)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			LocalAttribute pLocalAttribute;
			modelAttribute->getLocalAttribute(idx, pLocalAttribute);
			return s2ws1(pLocalAttribute.localName);
		}

		std::wstring getLocalAttributeByIndex_AbstractInfo(int modelAttributeObj, int idx)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			LocalAttribute pLocalAttribute;
			modelAttribute->getLocalAttribute(idx, pLocalAttribute);
			return s2ws1(pLocalAttribute.abstractInfo);
		}

		std::wstring getLocalAttributeByIndex_WikiUrl(int modelAttributeObj, int idx)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			LocalAttribute pLocalAttribute;
			modelAttribute->getLocalAttribute(idx, pLocalAttribute);
			return s2ws1(pLocalAttribute.wikiUrl);
		}

		int getLocalAttributeByIndex_KeywordCount(int modelAttributeObj, int idx)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			LocalAttribute pLocalAttribute;
			modelAttribute->getLocalAttribute(idx, pLocalAttribute);
			return pLocalAttribute.keywords.size();
		}

		std::wstring getLocalAttributeByIndex_KeywordWithIndex(int modelAttributeObj, int idx, int keywordIdx)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			LocalAttribute pLocalAttribute;
			modelAttribute->getLocalAttribute(idx, pLocalAttribute);
			return s2ws1(pLocalAttribute.keywords[idx]);
		}

		bool addLocalAttributeInfo(int modelAttributeObj, 
			ELocalizationType localType,
			std::wstring localName,
			std::wstring abstractInfo,
			std::wstring wikiUrl)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			LocalAttribute pLocalAttribute;
			pLocalAttribute.localType = localType;
			pLocalAttribute.localName = ws2s1(localName);
			pLocalAttribute.abstractInfo = ws2s1(abstractInfo);
			pLocalAttribute.wikiUrl = ws2s1(wikiUrl);
			return modelAttribute->addLocalAttributeInfo(pLocalAttribute);
		}

		bool addLocalAttributeInfo_Keyword(int modelAttributeObj, 
			ELocalizationType localType,
			std::wstring keyword)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			LocalAttribute localAttribute;
			bool exist = modelAttribute->getLocalAttribute(localType, localAttribute);
			if (exist)
			{
				localAttribute.keywords.push_back(ws2s1(keyword));
			}
			else return false;
			return modelAttribute->updateLocalAttribute(localType, localAttribute);
		}


		bool removeLocalAttributeByIndex(int modelAttributeObj, int idx)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			return modelAttribute->removeLocalAttribute(idx);
		}

		bool removeLocalAttributeByType(int modelAttributeObj, ELocalizationType pType)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			LocalAttribute pLocalAttribute;
			if (modelAttribute->getLocalAttribute(pType, pLocalAttribute))
				return modelAttribute->removeLocalAttribute(pLocalAttribute);
			return false;
		}

		int getCategoryCount(int modelAttributeObj)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			return modelAttribute->getCategoryCount();
		}

		std::wstring getCategory_Principle(int modelAttributeObj, int idx)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			 ModelCategory pModelCategory;
			 modelAttribute->getCategory(idx, pModelCategory);
			 return s2ws1(pModelCategory.principle);
		}

		std::wstring getCategory_Path(int modelAttributeObj, int idx)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			ModelCategory pModelCategory;
			modelAttribute->getCategory(idx, pModelCategory);
			return s2ws1(pModelCategory.path);
		}

		bool addCategoryInfo(int modelAttributeObj, std::wstring principle, std::wstring path)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			ModelCategory pModelCategory;
			pModelCategory.principle = ws2s1(principle);
			pModelCategory.path = ws2s1(path);
			return modelAttribute->addCategoryInfo(pModelCategory);
		}

		bool removeCategory(int modelAttributeObj, int idx)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			return modelAttribute->removeCategory(idx);
		}

		bool updateCategory(int modelAttributeObj, int idx, std::wstring principle, std::wstring path)
		{
			IModelAttribute* modelAttribute = (IModelAttribute*)modelAttributeObj;
			ModelCategory pModelCategory;
			pModelCategory.principle = ws2s1(principle);
			pModelCategory.path = ws2s1(path);
			return modelAttribute->updateCategory(idx, pModelCategory);
		}

		//////////////////////////////////////////////////////////////////////////
		//
		//
		//
		//////////////////////////////////////////////////////////////////////////
		bool addModelDatasetItem(int modelBehaviorObj,
			int datasetItem,
			std::wstring datasetName,
			EModelDatasetItemType datasetItemType,
			std::wstring datasetItemDescription,
			std::string externalId)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelDatasetItem modelDatasetItem;
			modelDatasetItem.datasetName = ws2s1(datasetName);
			modelDatasetItem.datasetItemType = datasetItemType;
			modelDatasetItem.datasetItemDescription = ws2s1(datasetItemDescription);
			modelDatasetItem.externalId = externalId;
			if (datasetItemType == EMDIT_INTERNAL)
			{
				NGIS::Data::Schema::IUdxDatasetSchema* datasetObj = (NGIS::Data::Schema::IUdxDatasetSchema*)datasetItem;
				modelDatasetItem.datasetItem = datasetObj;
			}
			else
			{
				modelDatasetItem.datasetItem = NULL;
			}
			return modelBehavior->addModelDatasetItem(modelDatasetItem);
		}

		bool removeModelDatasetItem(int modelBehaviorObj, std::wstring datasetName)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelDatasetItem pModelDatasetItem;
			modelBehavior->getModelDatasetItem(ws2s1(datasetName), pModelDatasetItem);
			return modelBehavior->removeModelDatasetItem(pModelDatasetItem);
		}

		int getModelDatasetItemCount(int modelBehaviorObj)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			return modelBehavior->getModelDatasetItemCount();
		}

		int getModelDatasetItem_Dataset(int modelBehaviorObj, int idx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelDatasetItem pModelDatasetItem;
			if (modelBehavior->getModelDatasetItem(idx,pModelDatasetItem))
			{
				return (int)pModelDatasetItem.datasetItem;
			}
			return -1;
		}

		std::wstring getModelDatasetItem_Name(int modelBehaviorObj, int idx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelDatasetItem pModelDatasetItem;
			if (modelBehavior->getModelDatasetItem(idx,pModelDatasetItem))
			{
				return s2ws1(pModelDatasetItem.datasetName);
			}
			return L"";
		}

		EModelDatasetItemType getModelDatasetItem_Type(int modelBehaviorObj, int idx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelDatasetItem pModelDatasetItem;
			if (modelBehavior->getModelDatasetItem(idx,pModelDatasetItem))
			{
				return pModelDatasetItem.datasetItemType;
			}
			return EModelDatasetItemType::EMDIT_EXTERNAL;
		}

		std::wstring getModelDatasetItem_Description(int modelBehaviorObj, int idx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelDatasetItem pModelDatasetItem;
			if (modelBehavior->getModelDatasetItem(idx,pModelDatasetItem))
			{
				return s2ws1(pModelDatasetItem.datasetItemDescription);
			}
			return L"";
		}

		std::string getModelDatasetItem_ExternalId(int modelBehaviorObj, int idx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelDatasetItem pModelDatasetItem;
			if (modelBehavior->getModelDatasetItem(idx,pModelDatasetItem))
			{
				return pModelDatasetItem.externalId;
			}
			return "";
		}

		//////////////////////////////////////////////////////////////////////////
		bool addModelState(int modelBehaviorObj, 
				std::string stateId,
				std::wstring stateName,
				EModelStateType stateType,
				std::wstring stateDecription)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			pState.stateId = (stateId);
			pState.stateName = ws2s1(stateName);
			pState.stateType = stateType;
			pState.stateDecription = ws2s1(stateDecription);

			return modelBehavior->addModelState(pState);
		}

		bool addModelState_Event(int modelBehaviorObj, std::wstring stateId, 
			std::wstring eventName,
			EModelEventType eventType,
			std::wstring eventDescription,
			std::wstring datasetReference,
			std::wstring parameterDescription,
			bool optional)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			modelBehavior->getModelState(ws2s1(stateId),pState);
			ModelEvent pEvent;
			pEvent.datasetReference = ws2s1(datasetReference);
			pEvent.eventDescription = ws2s1(eventDescription);
			pEvent.eventName = ws2s1(eventName);
			pEvent.eventType = eventType;
			pEvent.optional = optional;
			pEvent.parameterDescription = ws2s1(parameterDescription);
			pState.modelEvents.push_back(pEvent);
			return modelBehavior->updateModelState(ws2s1(stateId), pState);
		}

		bool removeModelState(int modelBehaviorObj, std::string stateId) 
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(stateId, pState))
			{
				return modelBehavior->removeModelState(pState);
			}
			return false;
		}

		int getModelStateCount(int modelBehaviorObj)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			return modelBehavior->getModelStateCount();
		}

		std::string getModelState_Id(int modelBehaviorObj, int idx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(idx, pState))
			{
				return pState.stateId;
			}
			return "";
		}

		std::wstring getModelState_Name(int modelBehaviorObj, int idx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(idx, pState))
			{
				return s2ws1(pState.stateName);
			}
			return L"";
		}

		EModelStateType getModelState_Type(int modelBehaviorObj, int idx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(idx, pState))
			{
				return pState.stateType;
			}
			return EModelStateType::EMST_BASIC;
		}

		std::wstring getModelState_Decription(int modelBehaviorObj, int idx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(idx, pState))
			{
				return s2ws1(pState.stateDecription);
			}
			return L"";
		}

		//////////////////////////////////////////////////////////////////////////
		int getModelState_EventCount(int modelBehaviorObj, int stateIdx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(stateIdx, pState))
			{
				return pState.modelEvents.size();
			}
			return 0;
		}

		std::wstring getModelState_Event_Name(int modelBehaviorObj, int stateIdx, int eventIdx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(stateIdx, pState))
			{
				ModelEvent pEvent = pState.modelEvents[eventIdx];
				return s2ws1(pEvent.eventName);
			}
			return L"";
		}

		EModelEventType getModelState_Event_Type(int modelBehaviorObj, int stateIdx, int eventIdx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(stateIdx, pState))
			{
				ModelEvent pEvent = pState.modelEvents[eventIdx];
				return pEvent.eventType;
			}
			return EModelEventType::EMET_CONTROL;
		}

		std::wstring getModelState_Event_Description(int modelBehaviorObj, int stateIdx, int eventIdx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(stateIdx, pState))
			{
				ModelEvent pEvent = pState.modelEvents[eventIdx];
				return s2ws1(pEvent.eventDescription);
			}
			return L"";
		}

		std::wstring getModelState_Event_DatasetReference(int modelBehaviorObj, int stateIdx, int eventIdx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(stateIdx, pState))
			{
				ModelEvent pEvent = pState.modelEvents[eventIdx];
				return s2ws1(pEvent.datasetReference);
			}
			return L"";
		}

		std::wstring getModelState_Event_ParameterDescription(int modelBehaviorObj, int stateIdx, int eventIdx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(stateIdx, pState))
			{
				ModelEvent pEvent = pState.modelEvents[eventIdx];
				return s2ws1(pEvent.parameterDescription);
			}
			return L"";
		}

		bool getModelState_Event_Optional(int modelBehaviorObj, int stateIdx, int eventIdx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(stateIdx, pState))
			{
				ModelEvent pEvent = pState.modelEvents[eventIdx];
				return pEvent.optional;
			}
			return false;
		}

		bool removeModelState_Event(int modelBehaviorObj, int stateIdx, int eventIdx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pState;
			if (modelBehavior->getModelState(stateIdx, pState))
			{
				pState.modelEvents.erase(pState.modelEvents.begin()+eventIdx);
				return modelBehavior->updateModelState(pState.stateId, pState);
			}
			return false;
		}

		//////////////////////////////////////////////////////////////////////////
		bool addModelStateTransition(int modelBehaviorObj, std::string pFromStateId, std::string pToStateId)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			return modelBehavior->addModelStateTransition(pFromStateId, pToStateId);
		}

		bool removeModelStateTransition(int modelBehaviorObj, std::string pFromStateId, std::string pToStateId)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			return modelBehavior->removeModelStateTransition(pFromStateId, pToStateId);
		}

		int getModelStateTransitionCount(int modelBehaviorObj)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			return modelBehavior->getModelStateTransitionCount();
		}

		std::string getModelStateTransition_From(int modelBehaviorObj, int idx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pFromState, pToState;
			modelBehavior->getModelStateTransition(idx, pFromState, pToState);
			return pFromState.stateId;
		}

		std::string getModelStateTransition_To(int modelBehaviorObj, int idx)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			ModelState pFromState, pToState;
			modelBehavior->getModelStateTransition(idx, pFromState, pToState);
			return pToState.stateId;
		}

		bool existModelStatetTransition(int modelBehaviorObj, std::string pFromStateId, std::string pToStateId)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			return modelBehavior->existModelStatetTransition(pFromStateId, pToStateId);
		}

		bool updateModelStateTransition(int modelBehaviorObj, int idx, std::string pFromStateId, std::string pToStateId)
		{
			IModelBehavior* modelBehavior = (IModelBehavior*)modelBehaviorObj;
			return modelBehavior->updateModelStateTransition(idx, pFromStateId, pToStateId);
		}

		//////////////////////////////////////////////////////////////////////////
		//
		//
		//
		//////////////////////////////////////////////////////////////////////////
		std::wstring getAliasName(int modelRuntimeObj)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			std::string name_str = modelRuntime->getName();
			return s2ws1(name_str);
		}

		void setAliasName(int modelRuntimeObj, std::wstring pName)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			std::string name_str = ws2s1(pName);
			modelRuntime->setName(name_str);
		}

		std::string getRuntimeVersion(int modelRuntimeObj)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			return modelRuntime->getVersion();
		}

		void setRuntimeVersion(int modelRuntimeObj, std::string pVersion)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			modelRuntime->setVersion(pVersion);
		}

		std::wstring getEntry(int modelRuntimeObj) 
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			std::string entry_str = modelRuntime->getEntry();
			return s2ws1(entry_str);
		}

		void setEntry(int modelRuntimeObj, std::wstring pEntry)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			std::string entry_str = ws2s1(pEntry);
			modelRuntime->setEntry(entry_str);
		}

		std::wstring getBaseDirectory(int modelRuntimeObj)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			std::string base_dir_str = modelRuntime->getBaseDirectory();
			return s2ws1(base_dir_str);
		}

		void setBaseDirectory(int modelRuntimeObj, std::wstring pDirectory)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			std::string base_dir_str = ws2s1(pDirectory);
			modelRuntime->setBaseDirectory(base_dir_str);
		}

		//////////////////////////////////////////////////////////////////////////
		bool addHardwareRequirement(int modelRuntimeObj,  std::wstring requirementKey, std::wstring requirementValue)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			HardwareRequirement pRequirement;
			pRequirement.requirementKey = ws2s1(requirementKey);
			pRequirement.requirementValue = ws2s1(requirementValue);
			return modelRuntime->addHardwareRequirement(pRequirement);
		}

		bool addSoftwareRequirement(int modelRuntimeObj,  std::wstring requirementKey, std::wstring requirementValue)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			SoftwareRequirement pRequirement;
			pRequirement.requirementKey = ws2s1(requirementKey);
			pRequirement.requirementValue = ws2s1(requirementValue);
			return modelRuntime->addSoftwareRequirement(pRequirement);
		}

		bool addModelAssembly(int modelRuntimeObj, std::wstring assemblyName, std::wstring assemblyPath)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			ModelAssembly pRequirement;
			pRequirement.assemblyName = ws2s1(assemblyName);
			pRequirement.assemblyPath = ws2s1(assemblyPath);
			return modelRuntime->addModelAssembly(pRequirement);
		}

		bool addSupportiveResource(int modelRuntimeObj, std::wstring resourceType, std::wstring resourceName)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			SupportiveResource pRequirement;
			pRequirement.resourceType = ws2s1(resourceType);
			pRequirement.resourceName = ws2s1(resourceName);
			return modelRuntime->addSupportiveResource(pRequirement);
		}

		int getHardwareRequirementCount(int modelRuntimeObj)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			return modelRuntime->getHardwareRequirementCount();
		}

		int getSoftwareRequirementCount(int modelRuntimeObj)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			return modelRuntime->getSoftwareRequirementCount();
		}

		int getModelAssemblyCount(int modelRuntimeObj)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			return modelRuntime->getModelAssemblyCount();
		}

		int getSupportiveResourceCount(int modelRuntimeObj)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			return modelRuntime->getSupportiveResourceCount();
		}

		std::wstring getHardwareRequirement_RequirementKey(int modelRuntimeObj, int idx)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			HardwareRequirement pRequirement;
			modelRuntime->getHardwareRequirement(idx, pRequirement);
			return s2ws1(pRequirement.requirementKey);
		}

		std::wstring getHardwareRequirement_RequirementValue(int modelRuntimeObj, int idx)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			HardwareRequirement pRequirement;
			modelRuntime->getHardwareRequirement(idx, pRequirement);
			return s2ws1(pRequirement.requirementValue);
		}

		std::wstring getSoftwareRequirement_RequirementKey(int modelRuntimeObj, int idx)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			SoftwareRequirement pRequirement;
			modelRuntime->getSoftwareRequirement(idx, pRequirement);
			return s2ws1(pRequirement.requirementKey);
		}

		std::wstring getSoftwareRequirement_RequirementValue(int modelRuntimeObj, int idx)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			SoftwareRequirement pRequirement;
			modelRuntime->getSoftwareRequirement(idx, pRequirement);
			return s2ws1(pRequirement.requirementValue);
		}

		std::wstring getModelAssembly_AssemblyName(int modelRuntimeObj, int idx)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			ModelAssembly pRequirement;
			modelRuntime->getModelAssembly(idx, pRequirement);
			return s2ws1(pRequirement.assemblyName);
		}

		std::wstring getModelAssembly_AssemblyPath(int modelRuntimeObj, int idx)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			ModelAssembly pRequirement;
			modelRuntime->getModelAssembly(idx, pRequirement);
			return s2ws1(pRequirement.assemblyPath);
		}

		std::wstring getSupportiveResource_ResourceType(int modelRuntimeObj, int idx)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			SupportiveResource pRequirement;
			modelRuntime->getSupportiveResource(idx, pRequirement);
			return s2ws1(pRequirement.resourceType);
		}

		std::wstring getSupportiveResource_ResourceName(int modelRuntimeObj, int idx)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			SupportiveResource pRequirement;
			modelRuntime->getSupportiveResource(idx, pRequirement);
			return s2ws1(pRequirement.resourceName);
		}

		bool removeHardwareRequirement(int modelRuntimeObj, int idx)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			return modelRuntime->removeHardwareRequirement(idx);
		}

		bool removeSoftwareRequirement(int modelRuntimeObj, int idx)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			return modelRuntime->removeSoftwareRequirement(idx);
		}

		bool removeModelAssembly(int modelRuntimeObj, int idx)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			return modelRuntime->removeModelAssembly(idx);
		}

		bool removeSupportiveResource(int modelRuntimeObj, int idx)
		{
			IModelRuntime* modelRuntime = (IModelRuntime*)modelRuntimeObj;
			return modelRuntime->removeSupportiveResource(idx);
		}

		//////////////////////////////////////////////////////////////////////////
		//
		//
		//
		//////////////////////////////////////////////////////////////////////////
		EMSCRIPTEN_BINDINGS(MDL_Module) {
			enum_<EExecutionStyle>("ModelExecutionStyle")
				.value("E_STATE_SIMULATION", EES_STATE_SIMULATION)
				.value("E_SIMPLE_CALCULATION", EES_SIMPLE_CALCULATION)
				.value("E_TIME_SERIES", EES_TIME_SERIES);

			enum_<ELocalizationType>("LocalizationType")
				.value("E_ZH_CN", ELT_ZH_CN)
				.value("E_EN_US", ELT_EN_US)
				.value("E_DE_DE", ELT_DE_DE)
				.value("E_RU_RU", ELT_RU_RU)
				.value("E_AR", ELT_AR)
				.value("E_ES", ELT_ES)
				.value("E_COUNT", ELT_COUNT);

			enum_<EModelEventType>("ModelEventType")
				.value("E_RESPONSE", EMET_RESPONSE)
				.value("E_NORESPONSE", EMET_NORESPONSE)
				.value("E_CONTROL", EMET_CONTROL);

			enum_<EModelStateType>("ModelStateType")
				.value("E_BASIC", EMST_BASIC)
				.value("E_GROUP", EMST_GROUP);

			enum_<EModelDatasetItemType>("ModelDatasetItemType")
				.value("E_INTERNAL", EMDIT_INTERNAL)
				.value("E_EXTERNAL", EMDIT_EXTERNAL)
				.value("E_RAW",EMDIT_RAW);

			function("getVersion1", &getVersion_js);
			function("createModelClass", &createModelClass_js);
			function("setModelName", &setModelName);
			function("setModelUID", &setModelUID);
			function("setModelExecutionStyle", &setModelExecutionStyle);
			function("getModelName", &getModelName);
			function("getModelUID", &getModelUID);
			function("getModelExecutionStyle", &getModelExecutionStyle);
			function("getModelAttribute", &getModelAttribute);
			function("getModelBehavior", &getModelBehavior);
			function("getModelRuntime", &getModelRuntime);
			function("LoadFromXmlStream", &loadFromXmlStream);
			function("FormatToXmlStream", &formatToXmlStream);
			function("CompareModelClassObject", &compareModelClass_object);
			function("CompareModelClassXML", &compareModelClass_xml);

			//////////////////////////////////////////////////////////////////////////
			function("getLocalAttributeCount", &getLocalAttributeCount);
			function("getLocalAttributeByIndex_LocalType", &getLocalAttributeByIndex_LocalType);
			function("getLocalAttributeByIndex_LocalName", &getLocalAttributeByIndex_LocalName);
			function("getLocalAttributeByIndex_AbstractInfo", &getLocalAttributeByIndex_AbstractInfo);
			function("getLocalAttributeByIndex_WikiUrl", &getLocalAttributeByIndex_WikiUrl);
			function("getLocalAttributeByIndex_KeywordCount", &getLocalAttributeByIndex_KeywordCount);
			function("getLocalAttributeByIndex_KeywordWithIndex", &getLocalAttributeByIndex_KeywordWithIndex);
			function("addLocalAttributeInfo", &addLocalAttributeInfo);
			function("addLocalAttributeInfo_Keyword", &addLocalAttributeInfo_Keyword);
			function("removeLocalAttributeByIndex", &removeLocalAttributeByIndex);
			function("removeLocalAttributeByType", &removeLocalAttributeByType);

			function("getCategoryCount", &getCategoryCount);
			function("getCategory_Principle", &getCategory_Principle);
			function("getCategory_Path", &getCategory_Path);
			function("addCategoryInfo", &addCategoryInfo);
			function("removeCategory", &removeCategory);
			function("updateCategory", &updateCategory);

			//////////////////////////////////////////////////////////////////////////
			function("addModelDatasetItem", &addModelDatasetItem);
			function("removeModelDatasetItem", &removeModelDatasetItem);
			function("getModelDatasetItemCount", &getModelDatasetItemCount);
			function("getModelDatasetItem_Dataset", &getModelDatasetItem_Dataset);
			function("getModelDatasetItem_Name", &getModelDatasetItem_Name);
			function("getModelDatasetItem_Type", &getModelDatasetItem_Type);
			function("getModelDatasetItem_Description", &getModelDatasetItem_Description);
			function("getModelDatasetItem_ExternalId", &getModelDatasetItem_ExternalId);

			//////////////////////////////////////////////////////////////////////////
			function("addModelState", &addModelState);
			function("addModelState_Event", &addModelState_Event);
			function("removeModelState", &removeModelState);
			function("getModelStateCount", &getModelStateCount);
			function("getModelState_Id", &getModelState_Id);
			function("getModelState_Name", &getModelState_Name);
			function("getModelState_Type", &getModelState_Type);
			function("getModelState_Decription", &getModelState_Decription);

			function("getModelState_EventCount", &getModelState_EventCount);
			function("getModelState_Event_Name", &getModelState_Event_Name);
			function("getModelState_Event_Type", &getModelState_Event_Type);
			function("getModelState_Event_Description", &getModelState_Event_Description);
			function("getModelState_Event_DatasetReference", &getModelState_Event_DatasetReference);
			function("getModelState_Event_ParameterDescription", &getModelState_Event_ParameterDescription);
			function("getModelState_Event_Optional", &getModelState_Event_Optional);
			function("removeModelState_Event", &removeModelState_Event);

			function("addModelStateTransition", &addModelStateTransition);
			function("removeModelStateTransition", &removeModelStateTransition);
			function("getModelStateTransitionCount", &getModelStateTransitionCount);
			function("getModelStateTransition_From", &getModelStateTransition_From);
			function("getModelStateTransition_To", &getModelStateTransition_To);
			function("existModelStatetTransition", &existModelStatetTransition);
			function("updateModelStateTransition", &updateModelStateTransition);

			//////////////////////////////////////////////////////////////////////////
			function("getAliasName", &getAliasName);
			function("setAliasName", &setAliasName);
			function("getRuntimeVersion", &getRuntimeVersion);
			function("setRuntimeVersion", &setRuntimeVersion);
			function("getEntry", &getEntry);
			function("setEntry", &setEntry);
			function("getBaseDirectory", &getBaseDirectory);
			function("setBaseDirectory", &setBaseDirectory);

			function("addHardwareRequirement", &addHardwareRequirement);
			function("addSoftwareRequirement", &addSoftwareRequirement);
			function("addModelAssembly", &addModelAssembly);
			function("addSupportiveResource", &addSupportiveResource);

			function("getHardwareRequirementCount", &getHardwareRequirementCount);
			function("getSoftwareRequirementCount", &getSoftwareRequirementCount);
			function("getModelAssemblyCount", &getModelAssemblyCount);
			function("getSupportiveResourceCount", &getSupportiveResourceCount);

			function("getHardwareRequirement_RequirementKey", &getHardwareRequirement_RequirementKey);
			function("getHardwareRequirement_RequirementValue", &getHardwareRequirement_RequirementValue);

			function("getSoftwareRequirement_RequirementKey", getSoftwareRequirement_RequirementKey);
			function("getSoftwareRequirement_RequirementValue", &getSoftwareRequirement_RequirementValue);

			function("getModelAssembly_AssemblyName", &getModelAssembly_AssemblyName);
			function("getModelAssembly_AssemblyPath", &getModelAssembly_AssemblyPath);

			function("getSupportiveResource_ResourceType", getSupportiveResource_ResourceType);
			function("getSupportiveResource_ResourceName", &getSupportiveResource_ResourceName);

			function("removeHardwareRequirement", &removeHardwareRequirement);
			function("removeSoftwareRequirement", &removeSoftwareRequirement);
			function("removeModelAssembly", removeModelAssembly);
			function("removeSupportiveResource", &removeSupportiveResource);
		}
	}
}


